import Taro, { AtToastUtil } from '@tarojs/taro'
import PropTypes from 'prop-types'
import { View, ScrollView } from '@tarojs/components'
import classNames from 'classnames'
import _findIndex from 'lodash/findIndex'
import _isUndefined from 'lodash/isUndefined'
import AtComponent from '../../common/component'
import AtIcon from '../icon'
import AtList from '../list/index'
import AtListItem from '../list-item/index'
import AtToast from '../toast/index'
import { delayQuerySelector, uuid, initTestEnv, isTest } from '../../common/utils'

initTestEnv()

class AtIndexes extends AtComponent {
  constructor() {
    super(...arguments)
    this.state = {
      _scrollIntoView: '',
      _scrollTop: 0,
      _tipText: '',
      isWEB: process.env.TARO_ENV === 'h5'
    }
    // 右侧导航高度
    this.menuHeight = 0
    // 右侧导航距离顶部高度
    this.startTop = 0
    // 右侧导航元素高度
    this.itemHeight = 0
    // 当前索引
    this.currentIndex = -1
    this.uid = uuid()
    this.listId = isTest() ? 'indexes-list-AOTU2018' : `list-${this.uid}`
    this.timeoutTimer = null
  }

  handleClick = (...arg) => this.props.onClick(...arg)

  handleTouchMove = event => {
    event.stopPropagation()
    // event.preventDefault()

    const { list } = this.props
    const pageY = event.touches[0].pageY
    const index = Math.floor((pageY - this.startTop) / this.itemHeight)

    if (index >= 0 && index <= list.length && this.currentIndex !== index) {
      this.currentIndex = index
      const key = index > 0 ? list[index - 1].key : 'top'
      const touchView = `at-indexes__list-${key}-${this.uid}`
      console.log(touchView)
      this.jumpTarget(touchView, index)
    }
  }

  handleTouchEnd = () => {
    this.currentIndex = -1
  }

  jumpTarget(_scrollIntoView, idx, idx2) {
    // toast不支持renderTop
    const { top, list } = this.props
    const _tipText = idx === 0 ? top : list[idx - 1].key

    if (process.env.TARO_ENV === 'h5') {
      // delayQuerySelector(this, '.at-indexes', 0).then(rect => {
      let targetOffsetTop = this.listRef.childNodes[idx].offsetTop
      if (Number(idx2)) {
        targetOffsetTop =
          this.listRef.childNodes[idx].childNodes[1].offsetTop +
          this.listRef.childNodes[idx].childNodes[1].childNodes[idx2 - 1].offsetTop
      }
      const _scrollTop = targetOffsetTop - this.listRef.offsetTop // rect[0].top
      this.updateState({
        _scrollTop,
        _scrollIntoView,
        _tipText
      })
      // })
      return
    }
    this.updateState({
      _scrollIntoView,
      _tipText
    })
  }

  __jumpTarget(parentKey, childKey) {
    const { list } = this.props
    let parentIndex = _findIndex(list, ['key', parentKey])
    let childIndex = -1
    let targetView = `at-indexes__list-${parentKey}-${this.uid}`
    if (childKey) {
      list.forEach((item, index1) => {
        item.items.forEach((item2, index2) => {
          if (item2.key === childKey) {
            parentIndex = index1
            childIndex = index2
          }
        })
      })
      targetView = `at-indexes__list-item-${childKey}-${this.uid}`
    } else if (parentKey === 'SCROLLTOTOP') {
      targetView = `at-indexes__top-${this.uid}`
      parentIndex = -1
    }
    this.jumpTarget(targetView, parentIndex + 1, childIndex + 1)
  }

  updateState(state) {
    const { toast, vibrate } = this.props
    const { _scrollIntoView, _tipText, _scrollTop } = state

    this.setState(
      {
        _scrollIntoView,
        _tipText,
        _scrollTop
      },
      () => {
        clearTimeout(this.timeoutTimer)
        // 支付宝微信下，需要重置，第二次点击才会生效
        this.setState({
          _scrollIntoView: ''
        })
        this.timeoutTimer = setTimeout(() => {
          this.setState({
            _tipText: ''
          })
          AtToastUtil.destroy()
        }, 3000)
      }
    )
    toast && AtToastUtil.show({ content: _tipText, duration: 2 })
    // 无法全局配置，该参数必须保留
    if (vibrate) {
      Taro.vibrateShort()
    }
  }

  initData() {
    delayQuerySelector(this, '.at-indexes__menu').then(rect => {
      const len = this.props.list.length
      this.menuHeight = rect[0].height
      this.startTop = rect[0].top
      this.itemHeight = Math.floor(this.menuHeight / (len + 1))
    })
  }

  handleScroll(e) {
    if (e && e.detail) {
      this.state._scrollTop = e.detail.scrollTop
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.list.length !== this.props.list.length) {
      this.initData()
    }
  }

  componentDidMount() {
    if (process.env.TARO_ENV === 'h5') {
      this.listRef = document.getElementById(this.listId)
    }
    this.initData()
  }

  componentWillMount() {
    this.props.onScrollIntoView && this.props.onScrollIntoView(this.__jumpTarget.bind(this))
  }

  render() {
    const { className, customStyle, animation, top, list, showCharacterIndexes } = this.props
    const { _scrollTop, _scrollIntoView, isWEB } = this.state

    const toastStyle = { minWidth: Taro.pxTransform(100) }
    const rootCls = classNames('at-indexes', className, {
      'at-indexes-hide-character': !showCharacterIndexes
    })

    const menuList = list.map((dataList, i) => {
      const { key } = dataList
      const targetView = `at-indexes__list-${key}-${this.uid}`
      return (
        <View
          className='at-indexes__menu-item'
          key={key + 1}
          onClick={this.jumpTarget.bind(this, targetView, i + 1)}
        >
          {key}
        </View>
      )
    })
    // item 里的key不是必须的，api暂不修改
    const indexesList = list.map(dataList => (
      <View
        id={`at-indexes__list-${dataList.key}-${this.uid}`}
        className='at-indexes__list'
        key={dataList.key}
      >
        <View className='at-indexes__list-title'>{dataList.title}</View>
        <AtList>
          {dataList.items &&
            dataList.items.map(item => (
              <AtListItem
                key={!_isUndefined(item.key) ? item.key : item.name}
                arrow={item.hasChildren ? 'right' : undefined}
                idName={`at-indexes__list-item-${item.key}-${this.uid}`}
                label={item.name}
                className={item.selected && 'list-item-selected'}
                onClick={this.handleClick.bind(this, item)}
              >
                {item.selected && !item.hasChildren && <AtIcon type='check'></AtIcon>}
              </AtListItem>
            ))}
        </AtList>
      </View>
    ))

    return (
      <View className={rootCls} style={customStyle}>
        <AtToast customStyle={toastStyle} />
        <View
          className='at-indexes__menu'
          onTouchMove={this.handleTouchMove}
          onTouchEnd={this.handleTouchEnd}
        >
          <View
            className='at-indexes__menu-item'
            onClick={this.jumpTarget.bind(this, `at-indexes__top-${this.uid}`, 0)}
          >
            {top}
          </View>
          {menuList}
        </View>
        <ScrollView
          className='at-indexes__body'
          id={this.listId}
          scrollY
          scrollWithAnimation={animation}
          scrollTop={isWEB ? _scrollTop : undefined}
          scrollIntoView={!isWEB ? _scrollIntoView : ''}
          onScroll={this.handleScroll.bind(this)}
        >
          <View className='at-indexes__content' id={`at-indexes__top-${this.uid}`}>
            {this.props.children}
          </View>
          {indexesList}
        </ScrollView>
      </View>
    )
  }
}

AtIndexes.propTypes = {
  customStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
  className: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
  animation: PropTypes.bool,
  vibrate: PropTypes.bool,
  toast: PropTypes.bool,
  top: PropTypes.string,
  list: PropTypes.array,
  onClick: PropTypes.func,
  onScrollIntoView: PropTypes.func,
  showCharacterIndexes: PropTypes.bool
}

AtIndexes.defaultProps = {
  isTest: false,
  customStyle: {},
  className: '',
  animation: false,
  top: 'Top',
  vibrate: true,
  toast: true,
  list: [],
  showCharacterIndexes: true,
  onClick: () => {},
  onScrollIntoView: () => {}
}

export default AtIndexes
